﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using ChannelVN.CMS.Common;
using ChannelVN.Cached.Config;
using Enyim.Caching;
using Enyim.Caching.Memcached;

namespace ChannelVN.Cached.CacheClients
{
    [Serializable]
    public class SimpleMemcachedKeyGroup : ISerializable
    {
        private readonly IDictionary<string, List<string>> _groups;

        private static MemcachedClient _systemMemcachedClient;

        private const int CacheExpiredForKeyGroups = 60 * 24 * 10; // in minute (10 days)
        private const string CacheNameForKeyGroups = "StorageForSimpleMemcachedKeys";

        public static SimpleMemcachedKeyGroup Current
        {
            get
            {
                try
                {
                    if (null == _systemMemcachedClient)
                        _systemMemcachedClient = new MemcachedClient("enyim.com/" + AppConfigs.DefaultMemcachedSectionName);

                    return _systemMemcachedClient.Get<SimpleMemcachedKeyGroup>(CacheNameForKeyGroups) ??
                           new SimpleMemcachedKeyGroup();
                }
                catch (Exception)
                {
                    return new SimpleMemcachedKeyGroup();
                }
            }
        }

        public List<string> this[string groupName]
        {
            get
            {
                return ContaintsGroup(groupName) ? _groups[groupName] : null;
            }
        }
        public string GetMemcachedKey(string groupName, string cachedKey)
        {
            if (ContaintsGroup(groupName))
            {
                var keyList = _groups[groupName];
                if (null != keyList)
                {
                    if (keyList.Any(key => key == cachedKey))
                    {
                        return GetPublishKey(groupName, cachedKey);
                    }
                }
            }
            return null;
        }
        public string UpdateKeyInfo(string groupName, string cachedKey)
        {
            if (ContaintsGroup(groupName))
            {
                var keyList = _groups[groupName];
                if (null != keyList)
                {
                    if (keyList.Any(key => key == cachedKey))
                    {
                        return GetPublishKey(groupName, cachedKey);
                    }
                    keyList.Add(cachedKey);
                    _groups[groupName] = keyList;
                }
            }
            else
            {
                var newKeyList = new List<string>();
                newKeyList.Add(cachedKey);
                _groups.Add(groupName, newKeyList);
            }
            SaveAllKeyGroup();
            return GetPublishKey(groupName, cachedKey);
        }
        public bool ContaintsGroup(string groupName)
        {
            return !string.IsNullOrEmpty(groupName) && _groups.ContainsKey(groupName);
        }

        public bool ContaintsKey(string groupName, string cachedKey)
        {
            if (string.IsNullOrEmpty(groupName) || string.IsNullOrEmpty(cachedKey)) return false;
            if (ContaintsGroup(groupName))
            {
                var keyList = _groups[groupName];
                if (null != keyList)
                {
                    return keyList.Any(key => key == cachedKey);
                }
            }
            return false;
        }
        public void RemoveKey(string groupName, string cachedKey)
        {
            if (!ContaintsGroup(groupName) || string.IsNullOrEmpty(cachedKey)) return;

            var keyList = _groups[groupName];

            if (null == keyList) return;

            keyList.Remove(cachedKey);
            SaveAllKeyGroup();
        }
        public void RemoveGroup(string groupName)
        {
            _groups.Remove(groupName);
            SaveAllKeyGroup();
        }
        public int GetKeyCountInGroup(string groupName)
        {
            return ContaintsGroup(groupName) ? (null != this[groupName] ? this[groupName].Count : 0) : 0;
        }
        public int GetGroupCount()
        {
            return _groups.Count;
        }
        private void SaveAllKeyGroup()
        {
            if (null == _systemMemcachedClient)
                _systemMemcachedClient = new MemcachedClient("enyim.com/" + AppConfigs.DefaultMemcachedSectionName);

            _systemMemcachedClient.Remove(CacheNameForKeyGroups);
            _systemMemcachedClient.Store(StoreMode.Add, CacheNameForKeyGroups, this, DateTime.Now.AddMinutes(CacheExpiredForKeyGroups));
        }
        public override string ToString()
        {
            return NewtonJson.Serialize(this);
        }

        public static string GetPublishKey(string groupName, string cachedKey)
        {
            return groupName + cachedKey;
        }
        public static string RemoveGroupFromCachedKey(string groupName, string publishKey)
        {
            return publishKey.Substring(groupName.Length);
        }

        public SimpleMemcachedKeyGroup()
        {
            _groups = new Dictionary<string, List<string>>();
        }
        public SimpleMemcachedKeyGroup(SerializationInfo info, StreamingContext ctxt)
        {
            _groups = (IDictionary<string, List<string>>)info.GetValue("_gs", typeof(IDictionary<string, List<string>>));
        }
        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("_gs", _groups);
        }
    }
}
